package com.zhtools.wx.bean;

import com.zhtools.wx.constants.WXPayConstants;
import com.zhtools.wx.exception.WXPayException;
import com.zhtools.wx.utils.WXPayUtil;
import org.apache.commons.lang.StringUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author zhanghao
 * 退款明细查询
 */
public class RefundQueryResponse implements Serializable {
    private static final long serialVersionUID = 312614437784984081L;

    private String returnCode;
    private String returnMsg;
    private String appId;
    private String mchId;
    private String nonceStr;
    private String sign;
    private String resultCode;
    private String errCode;
    private String errCodeDes;
    private Integer totalRefundCount;
    private String transactionId;
    private String outTradeNo;
    private Integer totalFee;
    private Integer settlementTotalFee;
    private String feeType;
    private Integer cashFee;
    private Integer refundCount;
    private List<RefundSubOrder> subOrders;

    public RefundQueryResponse() {
        this.subOrders = new ArrayList<>();
    }

    public String getReturnCode() {
        return returnCode;
    }

    public void setReturnCode(String returnCode) {
        this.returnCode = returnCode;
    }

    public String getReturnMsg() {
        return returnMsg;
    }

    public void setReturnMsg(String returnMsg) {
        this.returnMsg = returnMsg;
    }

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public String getMchId() {
        return mchId;
    }

    public void setMchId(String mchId) {
        this.mchId = mchId;
    }

    public String getNonceStr() {
        return nonceStr;
    }

    public void setNonceStr(String nonceStr) {
        this.nonceStr = nonceStr;
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    public String getResultCode() {
        return resultCode;
    }

    public void setResultCode(String resultCode) {
        this.resultCode = resultCode;
    }

    public String getErrCode() {
        return errCode;
    }

    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }

    public String getErrCodeDes() {
        return errCodeDes;
    }

    public void setErrCodeDes(String errCodeDes) {
        this.errCodeDes = errCodeDes;
    }

    public Integer getTotalRefundCount() {
        return totalRefundCount;
    }

    public void setTotalRefundCount(Integer totalRefundCount) {
        this.totalRefundCount = totalRefundCount;
    }

    public String getTransactionId() {
        return transactionId;
    }

    public void setTransactionId(String transactionId) {
        this.transactionId = transactionId;
    }

    public String getOutTradeNo() {
        return outTradeNo;
    }

    public void setOutTradeNo(String outTradeNo) {
        this.outTradeNo = outTradeNo;
    }

    public Integer getTotalFee() {
        return totalFee;
    }

    public void setTotalFee(Integer totalFee) {
        this.totalFee = totalFee;
    }

    public Integer getSettlementTotalFee() {
        return settlementTotalFee;
    }

    public void setSettlementTotalFee(Integer settlementTotalFee) {
        this.settlementTotalFee = settlementTotalFee;
    }

    public String getFeeType() {
        return feeType;
    }

    public void setFeeType(String feeType) {
        this.feeType = feeType;
    }

    public Integer getCashFee() {
        return cashFee;
    }

    public void setCashFee(Integer cashFee) {
        this.cashFee = cashFee;
    }

    public Integer getRefundCount() {
        return refundCount;
    }

    public void setRefundCount(Integer refundCount) {
        this.refundCount = refundCount;
    }

    public List<RefundSubOrder> getSubOrders() {
        return subOrders;
    }

    public void setSubOrders(List<RefundSubOrder> subOrders) {
        this.subOrders = subOrders;
    }

    @Override
    public String toString() {
        return "RefundQueryResponse{" +
                "returnCode='" + returnCode + '\'' +
                ", returnMsg='" + returnMsg + '\'' +
                ", appId='" + appId + '\'' +
                ", mchId='" + mchId + '\'' +
                ", nonceStr='" + nonceStr + '\'' +
                ", sign='" + sign + '\'' +
                ", resultCode='" + resultCode + '\'' +
                ", errCode='" + errCode + '\'' +
                ", errCodeDes='" + errCodeDes + '\'' +
                ", totalRefundCount=" + totalRefundCount +
                ", transactionId='" + transactionId + '\'' +
                ", outTradeNo='" + outTradeNo + '\'' +
                ", totalFee=" + totalFee +
                ", settlementTotalFee=" + settlementTotalFee +
                ", feeType='" + feeType + '\'' +
                ", cashFee=" + cashFee +
                ", refundCount=" + refundCount +
                ", subOrders=" + subOrders +
                '}';
    }

    public static RefundQueryResponse build(String xml, String signKey) throws WXPayException {
        boolean signOk = false;
        try {
            signOk = WXPayUtil.isSignatureValid(xml, signKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (!signOk) {
            throw new WXPayException(WXPayConstants.SIGNATURE_EXCEPTION);
        }

        Map<String, String> responseMap = null;
        try {
            responseMap = WXPayUtil.xmlToMap(xml);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (responseMap == null) {
            return null;
        }

        RefundQueryResponse instance = new RefundQueryResponse();
        instance.setReturnCode(responseMap.get("return_code"));
        instance.setReturnMsg(responseMap.get("return_msg"));
        instance.setResultCode(responseMap.get("result_code"));
        instance.setErrCode(responseMap.get("err_code"));
        instance.setErrCodeDes(responseMap.get("err_code_des"));
        instance.setAppId(responseMap.get("appid"));
        instance.setMchId(responseMap.get("mch_id"));
        instance.setNonceStr(responseMap.get("mch_id"));
        instance.setSign(responseMap.get("sign"));

        String total_refund_count_str = responseMap.get("total_refund_count");
        if(StringUtils.isNotEmpty(total_refund_count_str)){
            instance.setTotalRefundCount(Integer.parseInt(total_refund_count_str));
        }

        instance.setTransactionId(responseMap.get("transaction_id"));
        instance.setOutTradeNo(responseMap.get("out_trade_no"));
        instance.setTotalFee(Integer.parseInt(responseMap.get("total_fee")));
        instance.setSettlementTotalFee(Integer.parseInt(responseMap.get("settlement_total_fee")));
        instance.setFeeType(responseMap.get("fee_type"));
        instance.setCashFee(Integer.parseInt(responseMap.get("cash_fee")));
        instance.setRefundCount(Integer.parseInt(responseMap.get("refund_count")));

        for (int i = 0; i < instance.getRefundCount(); i++) {
            RefundSubOrder subOrder = new RefundSubOrder();
            subOrder.setOutRefundNo(responseMap.get("out_refund_no_" + i));
            subOrder.setRefundId(responseMap.get("refund_id_" + i));
            subOrder.setRefundChannel(responseMap.get("refund_channel_" + i));
            subOrder.setRefundFee(Integer.parseInt(responseMap.get("refund_fee_" + i)));
            subOrder.setSettlementRefundFee(Integer.parseInt(responseMap.get("settlement_refund_fee_") + i));
            subOrder.setCouponRefundCount(Integer.parseInt(responseMap.get("coupon_refund_count_" + i)));
            subOrder.setCouponRefundFee(Integer.parseInt(responseMap.get("coupon_refund_fee_" + i)));
            subOrder.setRefundStatus(responseMap.get("refund_status_" + i));
            subOrder.setRefundAccount(responseMap.get("refund_account_" + i));
            subOrder.setRefundRecvAccout(responseMap.get("refund_recv_accout_" + i));
            subOrder.setRefundSuccessTime(responseMap.get("refund_success_time_" + i));
            for (int j = 0; j < subOrder.getCouponRefundCount(); j++) {
                Coupon coupon = new Coupon();
                coupon.setCouponType(responseMap.get("coupon_type_" + i + "_" + j));
                coupon.setCouponRefundId(responseMap.get("coupon_refund_id_" + i + "_" + j));
                coupon.setCouponRefundFee(Integer.parseInt(responseMap.get("coupon_refund_fee_" + i + "_" + j)));
                subOrder.getCoupons().add(coupon);
            }
            instance.getSubOrders().add(subOrder);
        }
        return instance;
    }

    public static class RefundSubOrder implements Serializable {
        private static final long serialVersionUID = -8371840666113513386L;

        private String outRefundNo;
        private String refundId;
        private String refundChannel;
        private Integer refundFee;
        private Integer settlementRefundFee;
        private Integer couponRefundFee;
        private Integer couponRefundCount;
        private String refundStatus;
        private String refundAccount;
        private String refundRecvAccout;
        private String refundSuccessTime;
        private List<Coupon> coupons;

        public RefundSubOrder() {
            this.coupons = new ArrayList<>();
        }

        public String getOutRefundNo() {
            return outRefundNo;
        }

        public void setOutRefundNo(String outRefundNo) {
            this.outRefundNo = outRefundNo;
        }

        public String getRefundId() {
            return refundId;
        }

        public void setRefundId(String refundId) {
            this.refundId = refundId;
        }

        public String getRefundChannel() {
            return refundChannel;
        }

        public void setRefundChannel(String refundChannel) {
            this.refundChannel = refundChannel;
        }

        public Integer getRefundFee() {
            return refundFee;
        }

        public void setRefundFee(Integer refundFee) {
            this.refundFee = refundFee;
        }

        public Integer getSettlementRefundFee() {
            return settlementRefundFee;
        }

        public void setSettlementRefundFee(Integer settlementRefundFee) {
            this.settlementRefundFee = settlementRefundFee;
        }

        public Integer getCouponRefundFee() {
            return couponRefundFee;
        }

        public void setCouponRefundFee(Integer couponRefundFee) {
            this.couponRefundFee = couponRefundFee;
        }

        public Integer getCouponRefundCount() {
            return couponRefundCount;
        }

        public void setCouponRefundCount(Integer couponRefundCount) {
            this.couponRefundCount = couponRefundCount;
        }

        public String getRefundStatus() {
            return refundStatus;
        }

        public void setRefundStatus(String refundStatus) {
            this.refundStatus = refundStatus;
        }

        public String getRefundAccount() {
            return refundAccount;
        }

        public void setRefundAccount(String refundAccount) {
            this.refundAccount = refundAccount;
        }

        public String getRefundRecvAccout() {
            return refundRecvAccout;
        }

        public void setRefundRecvAccout(String refundRecvAccout) {
            this.refundRecvAccout = refundRecvAccout;
        }

        public String getRefundSuccessTime() {
            return refundSuccessTime;
        }

        public void setRefundSuccessTime(String refundSuccessTime) {
            this.refundSuccessTime = refundSuccessTime;
        }

        public List<Coupon> getCoupons() {
            return coupons;
        }

        public void setCoupons(List<Coupon> coupons) {
            this.coupons = coupons;
        }

        @Override
        public String toString() {
            return "RefundSubOrder{" +
                    "outRefundNo='" + outRefundNo + '\'' +
                    ", refundId='" + refundId + '\'' +
                    ", refundChannel='" + refundChannel + '\'' +
                    ", refundFee=" + refundFee +
                    ", settlementRefundFee=" + settlementRefundFee +
                    ", couponRefundFee=" + couponRefundFee +
                    ", couponRefundCount=" + couponRefundCount +
                    ", refundStatus='" + refundStatus + '\'' +
                    ", refundAccount='" + refundAccount + '\'' +
                    ", refundRecvAccout='" + refundRecvAccout + '\'' +
                    ", refundSuccessTime='" + refundSuccessTime + '\'' +
                    ", coupons=" + coupons +
                    '}';
        }
    }
}
